<template>
  <div
    style="position: relative;"
    :class="['w' + width]"
  >
    <el-progress
      v-show="progressShow"
      :percentage="percent"
    ></el-progress>
    <div
      class="uploader-wapper"
      @mouseleave="iconsShow = false"
    >
      <el-upload
        ref="upload"
        class="avatar-uploader"
        :action="action"
        :drag="true"
        :auto-upload="false"
        :headers="headers"
        :accept="accept"
        :show-file-list="false"
        :on-change="localUpload"
        :on-success="uploadSuccess"
        :before-upload="beforeUpload"
        :on-progress="uploadProgress"
        :on-error="uploadError"
      >
        <i class="el-icon-upload"></i>
        <div
          ref="imageUpload"
          class="el-upload__text"
          @mouseenter="listenPaste"
        >
          将文件<em>拖到</em>此处<br>或<em>点击上传</em>
        </div>
      </el-upload>
      <div
        v-if="url"
        class="imgOut"
      >
        <div @mouseover="iconsShow=!!url">
          <el-image
            ref="image"
            class="image"
            :src="url"
            :fit="'fit'"
            :preview-src-list="[url]"
            accept="image/*"
          ></el-image>
        </div>
      </div>
      <div
        v-if="iconsShow"
        class="delete"
      >
        <i
          v-if="canDelete"
          class="el-icon-delete"
          @click="deleteImg"
        ></i>
        <i
          v-if="canPreview"
          class="el-icon-view"
          @click="preview"
        ></i>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import PasteImg from '@/components/PasteImg/index.vue'
import request from '@/utils/request'
import { REQ_SUCCESS_CODE } from '@/constant/global'
@Component({
  name: 'UploadImg',
  components: {
    PasteImg
  }
})
export default class extends Vue {
  @Prop({ default: '/admin/media' }) api?: string
  @Prop({ default: '' }) url?: string
  @Prop({ default: 200 }) width?: number
  @Prop({ default: true }) canPreview?: boolean
  @Prop({ default: true }) canDelete?: boolean
  @Prop({ default: false }) disabled?: boolean
  @Prop({ default: false }) hasLibrary?: boolean

  // data
  pending = false
  iconsShow = false
  percent = 0
  progressShow = false

  isAddPasteListener = false
  pasteListener: any

  @Watch('pending')
  onPendingChange(v: boolean) {
    setTimeout(() => {
      this.progressShow = v
    }, v ? 0 : 500)
  }

  // computed
  get action() {
    return process.env.VUE_APP_BASE_API + (this.api as string)
  }

  get headers() {
    return {
      Authorization: 'Bearer ' + this.$store.state.user.token
    }
  }

  get accept() {
    return 'image/png, image/jpeg, image/gif, image/jpg'
  }

  mounted() {
    // this.$refs.upload && (this.$refs.upload as any).focus()
  }

  // methods
  // 粘贴上传
  async pasteUpload(blob: any) {
    const data = new FormData()
    data.append('file', blob)
    this.pending = true
    try {
      const res: any = await request({
        url: this.action,
        method: 'post',
        data,
        onUploadProgress: this.uploadProgress
      })
      if (res.code === REQ_SUCCESS_CODE) {
        this.$message.success('上传成功')
        const imgWH: any = await this.getHW(res.data)
        this.$emit('uploadSuccess', { url: res.data, width: imgWH.width, height: imgWH.height })
      } else throw res
    } catch (e) {
      console.log('上传失败')
    } finally {
      this.pending = false
    }
  }

  preview() {
    (this.$refs.image as any).clickHandler()
  }

  beforeUpload() {
    this.$emit('beforeUpload')
  }

  uploadProgress(e: any) {
    if (e.lengthComputable) {
      const num = e.loaded * 100 / e.total
      this.percent = parseInt(num.toString())
    }
  }

  paste(event:any) {
    const _this = this
    console.log('addEventListener: paste')
    if (event.clipboardData && event.clipboardData.items) {
      const items = event.clipboardData.items
      // event.preventDefault()
      for (var i = 0; i < items.length; i++) {
        if (items[i].type.indexOf('image') !== -1) {
          console.log(items[i].kind, items[i].type)
          var blob = items[i].getAsFile()
          if (blob && blob.size) {
            _this.pasteUpload(blob)
          }
        }
      }
    }
  }

  listenPaste() {
    // (this.$refs.imageUpload as any).focus()
    // if (this.isAddPasteListener) return
    // this.isAddPasteListener = true;

    // this.pasteListener = (event:any) => {
    //   console.log('addEventListener: paste')
    //   if (event.clipboardData && event.clipboardData.items) {
    //     const items = event.clipboardData.items
    //     event.preventDefault()
    //     for (var i = 0; i < items.length; i++) {
    //       if (items[i].type.indexOf('image') !== -1) {
    //         console.log(items[i].kind, items[i].type)
    //         var blob = items[i].getAsFile()
    //         if (blob && blob.size) {
    //           _this.pasteUpload(blob)
    //         }
    //       }
    //     }
    //   }
    // }

    // (this.$refs.imageUpload as any).addEventListener('paste', this.paste, true)
  }

  // 获取本地图片链接，图片上传中...
  localUpload(file: any) {
    this.pending = true
    if (file.status === 'ready') {
      (this as any).$emit('localPreview', window.URL.createObjectURL(file.raw));
      (this.$refs.upload as any).submit()
    }
  }

  getHW(url: string) {
    return new Promise((resolve) => {
      let res = {}
      const img = new Image()
      img.src = url
      img.onload = function() {
        res = {
          width: (this as any).width,
          height: (this as any).height
        }
        resolve(res)
      }
    })
  }

  // 上传成功， 去掉loading
  async uploadSuccess(res: any, file: any) {
    console.log(file)
    if (res.code === REQ_SUCCESS_CODE) {
      const imgWH: any = await this.getHW(res.data)
      this.$emit('uploadSuccess', { url: res.data, width: imgWH.width, height: imgWH.height })
      setTimeout(() => {
        this.pending = false
      })
      this.$message.success('上传成功')
    } else {
      this.uploadError()
    }
  }

  uploadError() {
    this.$emit('uploadError')
    this.$message.error('上传失败')
    setTimeout(() => {
      this.pending = false
    })
  }

  deleteImg() {
    this.iconsShow = false
    this.$emit('delete')
  }

  beforeDestroy() {
    (this.$refs.imageUpload as any).removeEventListener('paste', this.pasteListener)
  }
}
</script>

<style lang="scss" scoped>
  @mixin w($w) {
    width: $w;
    height: $w;
    // line-height: $w;
  }
  @mixin wh($w, $h) {
    width: $w;
    height: $h;
    line-height: $h;
  }
  @mixin commonW ($w){
    width: $w;
    ::v-deep .el-upload-dragger, .avatar-uploader-icon {
      @include w($w)
    }
    .image{
      @include w($w)
    }
  }
  @mixin commonWH ($w, $h){
    width: $w;
    ::v-deep .el-upload-dragger, .avatar-uploader-icon {
      @include wh($w, $h)
    }
    .image{
      @include wh($w, $h)
    }
  }
  .w100{
    @include commonW(100px)
  }
  .w200{
    @include commonW(200px)
  }
  .w300{
    @include commonW(300px)
  }
  .w400{
    @include commonW(400px)
  }
  .w-1{ @include commonWH(150px, 264px) }
  .w-2{ @include commonWH(400px, 200px) }
  .w-3{ @include commonWH(300px, 476px) }

  .uploader-wapper {
    position: relative;
    .avatar-uploader{
      ::v-deep .el-upload{
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
      }
      ::v-deep .el-upload:hover {
        border-color: #409EFF;
      }
    }

    .avatar-uploader-icon {
      font-size: 28px;
      color: #8c939d;
      text-align: center;
    }
    .avatar-uploader-icon:hover {
      border-color: #FF9480;
    }

    .avatar-uploader .el-upload:hover {
      border-color: #FF9480;
    }

    .imgOut{
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
    }
    .delete {
      position: absolute;
      background: rgba(0, 0, 0, 0.5);
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      display: flex;
      font-size: 30px;
      color: #ffffff;
      justify-content: space-around;
      align-items: center;
      i {
        cursor: pointer;
      }
    }
  }
</style>
